package org.nepu.scr.indexrate.raterisk.prerisk;

import cn.afterturn.easypoi.word.WordExportUtil;
import cn.afterturn.easypoi.word.entity.MyXWPFDocument;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.CopyOptions;
import cn.hutool.core.lang.Validator;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.AllArgsConstructor;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.lboot.core.domain.ResponseDTO;
import org.lboot.core.exception.BusinessException;
import org.lboot.jpa.utils.JpaDataUtil;
import org.lboot.ufs.service.UfsCtl;
import org.nepu.scr.indexrate.raterisk.prerisk.params.RiskCreateParams;
import org.nepu.scr.indexrate.raterisk.prerisk.params.RiskData;
import org.nepu.scr.indexrate.raterisk.prerisk.params.RiskQueryParams;
import org.nepu.scr.indexrate.raterisk.prerisk.params.RiskUpdateParams;
import org.nepu.scr.indexrate.raterisk.preriskparams.RiskParams;
import org.nepu.scr.indexrate.raterisk.preriskparams.RiskParamsController;
import org.nepu.scr.indexrate.raterisk.preriskparams.RiskParamsData;
import org.nepu.scr.indexrate.raterisk.preriskparams.RiskParamsService;
import org.nepu.scr.indexrate.raterisk.riskscore.RiskScoreController;
import org.nepu.scr.indexrate.raterisk.riskscore.RiskScoreService;
import org.nepu.scr.service.AnalyseService;
import org.nepu.scr.indexrate.raterisk.RiskBuildService;
//import org.nepu.scr.indexrate.raterisk.RiskMapService;
import org.nepu.scr.indexrate.raterisk.RiskDataService;
import org.springframework.data.domain.Example;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.http.HttpStatus;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.persistence.criteria.Predicate;
import javax.servlet.http.HttpServletResponse;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.*;

import static org.nepu.scr.constant.InLevelConstant.*;
import static org.nepu.scr.constant.SikeConstant.*;

@Slf4j
@RestController
@RequestMapping("safe")
@AllArgsConstructor
@Api(tags="作业前风险评级结果管理")
public class RiskController {

    public static String TARGET;
    PreRiskService riskService;

    RiskParamsService paramsService;

    RiskParamsController paramsController;

    UfsCtl ufsCtl;

    AnalyseService analyseService;

    RiskScoreService scoreService;

    RiskScoreController scoreController;

//    RiskMapService contentMapService;

    RiskDataService setDataService;

    RiskBuildService riskBuildService;

//    @PostMapping("risks")
//    @ApiOperation(value = "新建指标评价结果管理")
    public Risk dataCreate(@Validated @RequestBody RiskCreateParams params){

        if(params.getRiskId().equals("")){
            throw new BusinessException(HttpStatus.BAD_REQUEST,"评价任务ID不能为空");
        }

        RiskData data = new RiskData();
        List<Risk> dataList = riskService.getByRiskName(params.getRiskId());

        if (dataList.size() > 0){
            throw new BusinessException(HttpStatus.BAD_REQUEST,"存在指标评价任务"+params.getRiskId());
        }

        Risk risk = new Risk();
        risk.setRiskName(params.getRiskId());
        data.setRiskId(params.getRiskId());
        Risk r = riskService.saveOne(risk);
        String riskDataId = r.getId();
        riskService.saveRiskData(riskDataId, data);

        paramsController.dataCreate(params);
        return  r;
    }

//    @DeleteMapping("risks/{id}")
//    @ApiOperation(value = "删除指标评价结果")
    public String dataDelete(@PathVariable("id") String id){
        String ri = riskService.getOneUnwrap(id).getRiskName();
        riskService.deleteRiskData(id);
        riskService.deleteOne(id);
        List<RiskParams> riskParams = paramsService.getByRiskName(ri);
        paramsController.dataDelete(riskParams.get(0).getId());
        return "删除成功";
    }


    @PutMapping("risks/{riskId}/data")
    @ApiOperation(value = "评价结果更新")
    public ResponseDTO<Object> dataUpdate(@PathVariable("riskId") String riskId,@Validated @RequestBody RiskUpdateParams params){
        String scoreId = params.getScoreId();
        RiskData data = riskService.readRiskData(riskId);
//        BeanUtil.copyProperties(params,data, CopyOptions.create().setIgnoreNullValue(true).setIgnoreError(true));
        //更新参数
        RiskParams p = new RiskParams();
        p.setRiskName(riskService.getOneUnwrap(riskId).getRiskName());
        Example<RiskParams> example = Example.of(p);
        List<RiskParams> params1 = paramsService.getExample(example);
        RiskParamsData paramsData = new RiskParamsData();
        BeanUtil.copyProperties(params,paramsData, CopyOptions.create().setIgnoreNullValue(true).setIgnoreError(true));
        paramsController.dataUpdate(params1.get(0).getId(),paramsData);

        String input = null;
        for(int i=0;i<SOURCE.length;i++){
            if(params.getRiskScore().containsKey(SOURCE[i])){
                input = SOURCE[i];
                break;
            }
        }
        if(Validator.isEmpty(input)){
            throw new BusinessException(HttpStatus.BAD_REQUEST,"输入源错误，无法计算");
        }


        //输入源为B1
        if(params.getRiskScore().containsKey("B1")){
            TARGET = "B1";
            setDataService.setData(data,judgeGrade(params.getRiskScore().get("B1")),TARGET);
            if(Validator.isNotEmpty(data.getB1())&&
                    Validator.isNotEmpty(data.getB2())&&
                    Validator.isNotEmpty(data.getB3())&&
                    Validator.isNotEmpty(data.getB4())&&
                    Validator.isNotEmpty(data.getB5())){
                String resultB = analyseService.analyse(scoreService.readRiskData(scoreId).getB(), buildMatrix("B",data));
                setDataService.setData(data,resultB,TARGET);
            }
        }
        //输入源为B5
        if(params.getRiskScore().containsKey("B5")){
            TARGET = "B5";
            setDataService.setData(data,judgeGrade(params.getRiskScore().get("B5")),TARGET);
            if(Validator.isNotEmpty(data.getB1())&&
                    Validator.isNotEmpty(data.getB2())&&
                    Validator.isNotEmpty(data.getB3())&&
                    Validator.isNotEmpty(data.getB4())&&
                    Validator.isNotEmpty(data.getB5())){
                String resultB = analyseService.analyse(scoreService.readRiskData(scoreId).getB(), buildMatrix("B",data));
                setDataService.setData(data,resultB,TARGET);
            }
        }

        //输入原为B3
        if(params.getRiskScore().containsKey("B3")){
            TARGET = "B3";
            setDataService.setData(data,judgeGrade(params.getRiskScore().get("B3")),TARGET);
            if(Validator.isNotEmpty(data.getB1())&&
                    Validator.isNotEmpty(data.getB2())&&
                    Validator.isNotEmpty(data.getB3())&&
                    Validator.isNotEmpty(data.getB4())&&
                    Validator.isNotEmpty(data.getB5())){
                String resultB = analyseService.analyse(scoreService.readRiskData(scoreId).getB(), buildMatrix("B",data));
                setDataService.setData(data,resultB,TARGET);
            }
        }

        //输入原为B4x
        String inputB4x = null;
        for(int i=0;i<B4.length;i++){
            if(params.getRiskScore().containsKey(B4[i])){
                inputB4x = B4[i];
                break;
            }
        }
        if(Validator.isNotEmpty(inputB4x)){
            TARGET = inputB4x;
            setDataService.setData(data,judgeGrade(params.getRiskScore().get(TARGET)),TARGET);
            if(Validator.isNotEmpty(data.getB41())&&
                    Validator.isNotEmpty(data.getB42())&&
                    Validator.isNotEmpty(data.getB43())&&
                    Validator.isNotEmpty(data.getB44())&&
                    Validator.isNotEmpty(data.getB45())&&
                    Validator.isNotEmpty(data.getB46())&&
                    Validator.isNotEmpty(data.getB47())&&
                    Validator.isNotEmpty(data.getB48())&&
                    Validator.isNotEmpty(data.getB49())&&
                    Validator.isNotEmpty(data.getB4a())&&
                    Validator.isNotEmpty(data.getB4b())&&
                    Validator.isNotEmpty(data.getB4c())){
                String resultB4 = analyseService.analyse(scoreService.readRiskData(scoreId).getB4(), buildMatrix("B4",data));
                setDataService.setData(data,resultB4,TARGET);
                if(Validator.isNotEmpty(data.getB1())&&
                        Validator.isNotEmpty(data.getB2())&&
                        Validator.isNotEmpty(data.getB3())&&
                        Validator.isNotEmpty(data.getB4())&&
                        Validator.isNotEmpty(data.getB5())){
                    String resultB = analyseService.analyse(scoreService.readRiskData(scoreId).getB(), buildMatrix("B",data));
                    setDataService.setData(data,resultB,TARGET);
                }
            }
        }

        //输入原为B21
        if(params.getRiskScore().containsKey("B21")){
            TARGET = "B21";
            setDataService.setData(data,judgeGrade(params.getRiskScore().get("B21")),TARGET);
            if(Validator.isNotEmpty(data.getB21())&&
                    Validator.isNotEmpty(data.getB22())&&
                    Validator.isNotEmpty(data.getB23())){
                String resultB2 = analyseService.analyse(scoreService.readRiskData(scoreId).getB2(), buildMatrix("B2",data));
                setDataService.setData(data,resultB2,TARGET);
                if(Validator.isNotEmpty(data.getB1())&&
                        Validator.isNotEmpty(data.getB2())&&
                        Validator.isNotEmpty(data.getB3())&&
                        Validator.isNotEmpty(data.getB4())&&
                        Validator.isNotEmpty(data.getB5())){
                    String resultB = analyseService.analyse(scoreService.readRiskData(scoreId).getB(), buildMatrix("B",data));
                    setDataService.setData(data,resultB,TARGET);
                }
            }
        }

        //输入原为B22x
        String inputB22x = null;
        for(int i=0;i<B22.length;i++){
            if(params.getRiskScore().containsKey(B22[i])){
                inputB22x = B22[i];
                break;
            }
        }
        if(Validator.isNotEmpty(inputB22x)){
            TARGET = inputB22x;
            setDataService.setData(data,judgeGrade(params.getRiskScore().get(TARGET)),TARGET);
            if(Validator.isNotEmpty(data.getB221())&&
                    Validator.isNotEmpty(data.getB222())&&
                    Validator.isNotEmpty(data.getB223())&&
                    Validator.isNotEmpty(data.getB224())&&
                    Validator.isNotEmpty(data.getB225())&&
                    Validator.isNotEmpty(data.getB226())&&
                    Validator.isNotEmpty(data.getB227())&&
                    Validator.isNotEmpty(data.getB228())&&
                    Validator.isNotEmpty(data.getB229())&&
                    Validator.isNotEmpty(data.getB22a())&&
                    Validator.isNotEmpty(data.getB22b())&&
                    Validator.isNotEmpty(data.getB22c())&&
                    Validator.isNotEmpty(data.getB22d())&&
                    Validator.isNotEmpty(data.getB22e())&&
                    Validator.isNotEmpty(data.getB22f())&&
                    Validator.isNotEmpty(data.getB22g())&&
                    Validator.isNotEmpty(data.getB22h())){
                String resultB22 = analyseService.analyse(scoreService.readRiskData(scoreId).getB22(), buildMatrix("B22",data));
                setDataService.setData(data,resultB22,TARGET);
                if(Validator.isNotEmpty(data.getB21())&&
                        Validator.isNotEmpty(data.getB22())&&
                        Validator.isNotEmpty(data.getB23())){
                    String resultB2 = analyseService.analyse(scoreService.readRiskData(scoreId).getB2(), buildMatrix("B2",data));
                    setDataService.setData(data,resultB2,TARGET);
                    if(Validator.isNotEmpty(data.getB1())&&
                            Validator.isNotEmpty(data.getB2())&&
                            Validator.isNotEmpty(data.getB3())&&
                            Validator.isNotEmpty(data.getB4())&&
                            Validator.isNotEmpty(data.getB5())){
                        String resultB = analyseService.analyse(scoreService.readRiskData(scoreId).getB(), buildMatrix("B",data));
                        setDataService.setData(data,resultB,TARGET);
                    }
                }
            }
        }

        //输入原为B23x
        String inputB23x = null;
        for(int i=0;i<B23.length;i++){
            if(params.getRiskScore().containsKey(B23[i])){
                inputB23x = B23[i];
                break;
            }
        }
        if(Validator.isNotEmpty(inputB23x)) {
            TARGET = inputB23x;
            setDataService.setData(data,judgeGrade(params.getRiskScore().get(TARGET)),TARGET);
            if(Validator.isNotEmpty(data.getB231())&&
                    Validator.isNotEmpty(data.getB232())&&
                    Validator.isNotEmpty(data.getB233())&&
                    Validator.isNotEmpty(data.getB234())&&
                    Validator.isNotEmpty(data.getB235())&&
                    Validator.isNotEmpty(data.getB236())){
                String resultB23 = analyseService.analyse(scoreService.readRiskData(scoreId).getB23(), buildMatrix("B23",data));
                setDataService.setData(data,resultB23,TARGET);
                if(Validator.isNotEmpty(data.getB21())&&
                        Validator.isNotEmpty(data.getB22())&&
                        Validator.isNotEmpty(data.getB23())){
                    String resultB2 = analyseService.analyse(scoreService.readRiskData(scoreId).getB2(), buildMatrix("B2",data));
                    setDataService.setData(data,resultB2,TARGET);
                    if(Validator.isNotEmpty(data.getB1())&&
                            Validator.isNotEmpty(data.getB2())&&
                            Validator.isNotEmpty(data.getB3())&&
                            Validator.isNotEmpty(data.getB4())&&
                            Validator.isNotEmpty(data.getB5())){
                        String resultB = analyseService.analyse(scoreService.readRiskData(scoreId).getB(), buildMatrix("B",data));
                        setDataService.setData(data,resultB,TARGET);
                    }
                }
            }
        }

        RiskData returnData = riskService.saveRiskData(riskId, data);

        return ResponseDTO.succData(
                riskBuildService.buildData(returnData)
        );
    }

    @GetMapping("risks")
    @ApiOperation(value = "指标评价结果列表")
    public ResponseDTO<Object> dataList(RiskQueryParams params){
        Pageable pageable = JpaDataUtil.buildPageable(params);
        if (Validator.isEmpty(params.getSearchKey())){
            Risk data = new Risk();
            BeanUtil.copyProperties(params,data, CopyOptions.create().setIgnoreNullValue(true).setIgnoreError(true));
            Example<Risk> example = Example.of(data);
            return ResponseDTO.succData(
                    riskService.getAll(pageable,example)
            );
        }else {
            Specification<Risk> spec = (root, query, cb) -> {
                List<Predicate> list = new ArrayList<>();
                Predicate p1 = cb.like(root.get("riskId").as(String.class),"%"+params.getSearchKey()+"%");
                list.add(p1);
                Predicate[] predicates = new Predicate[list.size()];
                return cb.or(list.toArray(predicates));
            };
            return ResponseDTO.succData(
                    riskService.getAll(pageable, spec)
            );
        }
    }

    @GetMapping("risks/{id}")
    @ApiOperation(value = "指标评价结果查询")
    public ResponseDTO<Object> dataQuery(@PathVariable("id") String id){
        RiskData riskData = riskService.readRiskData(id);
        return ResponseDTO.succData(
                riskBuildService.buildData(riskData)
        );
    }

//    @GetMapping("risks/schemes/export")
//    @ApiOperation(value = "指标评价结果导出")
//    @SneakyThrows
//    public void wordExport(@RequestParam("riskDataId") String riskDataId,@RequestParam("riskParamsId") String riskParamsId, @RequestParam(value = "templateFileId",required = false) String templateFileId
//            , HttpServletResponse response){
//        InputStream stream = ufsCtl.getFileStream(templateFileId);
//        RiskParamsData exportParamsData = paramsService.readRiskData(riskParamsId);
//        RiskData exportData = riskService.readRiskData(riskDataId);
//        XWPFDocument document = new MyXWPFDocument(stream);
//        //生成文本内容Map
//        Map<String, Object> contentMap = contentMapService.buildContentMap(riskDataId,riskParamsId,exportData,exportParamsData);
//
//        //替换文本内容
//        WordExportUtil.exportWord07(document, contentMap);
//
//        //返回流
//        response.setHeader("content-type", "application/octet-stream");
//        response.setContentType("application/octet-stream;charset=UTF-8");
//        /**
//         * 修改导出文件名称
//         */
//        String encodedFileName = URLEncoder.encode(exportData.getRiskId() + "安全评价报告.docx", StandardCharsets.UTF_8.toString());
//        response.setHeader("Content-Disposition", "attachment; filename=\"" + encodedFileName + "\"; filename*=utf-8''" + encodedFileName);
////        response.setHeader("Content-Disposition", "attachment; filename=" + encodedFileName+".docx");
//        OutputStream outputStream = response.getOutputStream();
//        document.write(outputStream);
//        outputStream.flush();
//
//        outputStream.close();
//    }


    //构建隶属度矩阵
    // A   优秀 良好 一般 较差 极差
    // A1  1    0   0   0   0
    // A2  1    0   0   0   0
    // A3  0    0   0   0   1
    // A4  0    1   0   0   0
    @SneakyThrows
    public Double[][] buildMatrix(String input, RiskData data){

        Double[][] matrix = null;

        if(input.equals("B")) {
            //B存在构建B隶属度矩阵
            Double[][] m = new Double[B.length][GRADE];
            m[0] = buildMatrix(judgeNumber(data.getB1()));
            m[1] = buildMatrix(judgeNumber(data.getB2()));
            m[2] = buildMatrix(judgeNumber(data.getB3()));
            m[3] = buildMatrix(judgeNumber(data.getB4()));
            m[4] = buildMatrix(judgeNumber(data.getB5()));
            TARGET = "B";
            matrix=m;
        }else if(input.equals("B2")){
            //构建B2隶属度矩阵
            Double[][] m = new Double[B2.length][GRADE];
            m[0] = buildMatrix(judgeNumber(data.getB21()));
            m[1] = buildMatrix(judgeNumber(data.getB22()));
            m[2] = buildMatrix(judgeNumber(data.getB23()));
            TARGET = "B2";
            matrix=m;
        }else if(input.equals("B4")){
            //构建B4隶属度矩阵
            Double[][] m = new Double[B4.length][GRADE];
            m[0] = buildMatrix(judgeNumber(data.getB41()));
            m[1] = buildMatrix(judgeNumber(data.getB42()));
            m[2] = buildMatrix(judgeNumber(data.getB43()));
            m[3] = buildMatrix(judgeNumber(data.getB44()));
            m[4] = buildMatrix(judgeNumber(data.getB45()));
            m[5] = buildMatrix(judgeNumber(data.getB46()));
            m[6] = buildMatrix(judgeNumber(data.getB47()));
            m[7] = buildMatrix(judgeNumber(data.getB48()));
            m[8] = buildMatrix(judgeNumber(data.getB49()));
            m[9] = buildMatrix(judgeNumber(data.getB4a()));
            m[10] = buildMatrix(judgeNumber(data.getB4b()));
            m[11] = buildMatrix(judgeNumber(data.getB4c()));
            TARGET = "B4";
            matrix=m;
        }else if(input.equals("B22")){
            //构建B22隶属度矩阵
            Double[][] m = new Double[B22.length][GRADE];
            m[0] = buildMatrix(judgeNumber(data.getB221()));
            m[1] = buildMatrix(judgeNumber(data.getB222()));
            m[2] = buildMatrix(judgeNumber(data.getB223()));
            m[3] = buildMatrix(judgeNumber(data.getB224()));
            m[4] = buildMatrix(judgeNumber(data.getB225()));
            m[5] = buildMatrix(judgeNumber(data.getB226()));
            m[6] = buildMatrix(judgeNumber(data.getB227()));
            m[7] = buildMatrix(judgeNumber(data.getB228()));
            m[8] = buildMatrix(judgeNumber(data.getB229()));
            m[9] = buildMatrix(judgeNumber(data.getB22a()));
            m[10] = buildMatrix(judgeNumber(data.getB22b()));
            m[11] = buildMatrix(judgeNumber(data.getB22c()));
            m[12] = buildMatrix(judgeNumber(data.getB22d()));
            m[13] = buildMatrix(judgeNumber(data.getB22e()));
            m[14] = buildMatrix(judgeNumber(data.getB22f()));
            m[15] = buildMatrix(judgeNumber(data.getB22g()));
            m[16] = buildMatrix(judgeNumber(data.getB22h()));
            TARGET = "B22";
            matrix=m;
        }else if(input.equals("B23")){
            //构建B23隶属度矩阵
            Double[][] m = new Double[B23.length][GRADE];
            m[0] = buildMatrix(judgeNumber(data.getB231()));
            m[1] = buildMatrix(judgeNumber(data.getB232()));
            m[2] = buildMatrix(judgeNumber(data.getB233()));
            m[3] = buildMatrix(judgeNumber(data.getB234()));
            m[4] = buildMatrix(judgeNumber(data.getB235()));
            m[5] = buildMatrix(judgeNumber(data.getB236()));
            TARGET = "B23";
            matrix=m;
        }else {
            throw new BusinessException(HttpStatus.BAD_REQUEST,"构建隶属度矩阵失败");
        }

        return  matrix;
    }

    //构建隶属度数组
    public static Double[] buildMatrix(Double d){
        Double[] result = {0.0,0.0,0.0,0.0,0.0};

        if(d>1.0){
            throw new BusinessException(HttpStatus.BAD_REQUEST,"输入指标比错误应大于等于0.0小于1.0");
        } else if (d >= ONE) {
            result[0] = 1.0;
        } else if (d >= TWO) {
            result[1] = 1.0;
        } else if (d >= THREE) {
            result[2] = 1.0;
        } else if (d >= FORE) {
            result[3] = 1.0;
        } else if (d >= FIVE) {
            result[4] = 1.0;
        }else {
            throw new BusinessException(HttpStatus.BAD_REQUEST,"输入指标比错误应大于等于0.0小于1.0");
        }
        return result;
    }

    @SneakyThrows
    public static Double judgeNumber (String grade){
        if(grade.equals(ONEG)){
            return ONE;
        }else if (grade.equals(TWOG)){
            return TWO;
        }else if (grade.equals(THREEG)){
            return THREE;
        }else if (grade.equals(FOREG)){
            return FORE;
        }else{
            return FIVE;
        }
    }


    //矩阵输出
    @SneakyThrows
    public static void printMatrix(Double[][] matrix){
        System.out.println("矩阵输出：");
        for (int i = 0; i < matrix.length; i++) {
            System.out.print("[");
            for (int j = 0; j < matrix[i].length; j++) {
                System.out.print(matrix[i][j]+" ");
            }
            System.out.println("]");
        }
    }

    //判断子指标是否完整
    @SneakyThrows
    public static Boolean keysToCheck (Map<String,Double> scoreMap,String[] keys){
        Boolean exist = true;
        for (String key : keys) {
            if (!scoreMap.containsKey(key)) {
                exist = false;
                break;
            }
        }
        return exist;
    }


    @SneakyThrows
    public static String judgeGrade (Double maxIndex){
        if(maxIndex>1.0){
            throw new BusinessException(HttpStatus.BAD_REQUEST,"输入指标比错误应大于等于0.0小于1.0");
        }
        if(maxIndex<0.0){
            throw new BusinessException(HttpStatus.BAD_REQUEST,"输入指标比错误应大于等于0.0小于1.0");
        }
        if(maxIndex>=ONE){
            return ONEG;
        }else if (maxIndex>=TWO){
            return TWOG;
        }else if (maxIndex>=THREE){
            return THREEG;
        }else if (maxIndex>=FORE){
            return FOREG;
        }else{
            return FIVEG;
        }
    }
}
